#ifndef RADIAN_H
#define RADIAN_H

#include "Framework/Prerequisites.h"

namespace tyro
{
	namespace Math
	{
		template <class T>
		class Radian
		{
			public:

				T	radian;

				/* Default Constructor */
				explicit Radian<T>( T rad=0 ) : radian(rad) {}

				/* Multi-Contructors */
				Radian<T>( const Degree<T>& deg );


				/* Assignment Operators */
				inline Radian<T>& operator = ( const T& val ) { radian = val; return *this; }
				inline Radian<T>& operator = ( const Radian<T>& rad ) { radian = rad.radian; return *this; }
				inline Radian<T>& operator = ( const Degree<T>& deg );

				/* Relational and Equality Operators */
				inline bool operator == ( const Radian<T>& rad ) const { return radian == rad.radian; }
				inline bool operator != ( const Radian<T>& rad ) const { return radian != rad.radian; }
				inline bool operator <  ( const Radian<T>& rad ) const { return radian <  rad.radian; }
				inline bool operator <= ( const Radian<T>& rad ) const { return radian <= rad.radian; }
				inline bool operator >  ( const Radian<T>& rad ) const { return radian >  rad.radian; }
				inline bool operator >= ( const Radian<T>& rad ) const { return radian >= rad.radian; }

				/* Binary Arithmetic Operators */
				inline const Radian<T>& operator + () const { return *this; }
				inline Radian<T> operator + ( const Radian<T>& rad ) const { return Radian<T>( radian + rad.radian ); }
				inline Radian<T> operator + ( const Degree<T>& deg ) const;
				inline Radian<T> operator - () const { return Radian<T>(-radian); }
				inline Radian<T> operator - ( const Radian<T>& rad ) const { return Radian<T>( radian - rad.radian ); }
				inline Radian<T> operator - ( const Degree<T>& deg ) const;
				inline Radian<T> operator * ( T val ) const { return Radian<T> ( radian * val ); }
				inline Radian<T> operator * ( const Radian<T>& rad ) const { return Radian<T> ( radian * rad.radian ); }

				inline friend const Radian<T> operator * ( T val, const Radian<T>& rad)
				{
					return Radian<T>(val * rad.radian);
				}

				inline Radian<T> operator / ( T val ) const { return Radian<T>( radian / val ); }


				/* Compound Assignment Operators */
				inline Radian<T>& operator += ( const Radian<T>& rad ) { radian += rad.radian; return *this; }
				inline Radian<T>& operator += ( const Degree<T>& deg );
				inline Radian<T>& operator -= ( const Radian<T>& rad ) { radian -= rad.radian; return *this; }
				inline Radian<T>& operator -= ( const Degree<T>& deg );
				inline Radian<T>& operator *= ( T val ) { radian *= val; return *this; }
				inline Radian<T>& operator /= ( T val ) { radian /= val; return *this; }


				T ToDegrees() const;
				T ToRadians() const { return radian; }
				

			protected:
			private:
		};

		template <class T>
		T tyro::Math::Radian<T>::ToDegrees() const
		{
			return Math::RadiansToDegrees(radian);
		}

		template <class T>
		tyro::Math::Radian<T>::Radian( const Degree<T>& deg )
		{
			return Radian<T>( Math::DegreesToRadian(deg) ); 
		}

		template <class T>
		inline Radian<T>& tyro::Math::Radian<T>::operator = ( const Degree<T>& deg )
		{
			radian = Math::DegreesToRadian(deg);
			return *this;
		}

		template <class T>
		inline Radian<T> tyro::Math::Radian<T>::operator + ( const Degree<T>& deg ) const
		{
			return Radian( radian + Math::DegreesToRadian(deg));
		}

		template <class T>
		inline Radian<T> tyro::Math::Radian<T>::operator - ( const Degree<T>& deg ) const
		{
			return Radian( radian - Math::DegreesToRadian(deg));
		}

		template <class T>
		inline Radian<T>& tyro::Math::Radian<T>::operator += ( const Degree<T>& deg )
		{
			radian += Math::DegreesToRadian(deg);
			return *this;
		}

		template <class T>
		inline Radian<T>& tyro::Math::Radian<T>::operator -= ( const Degree<T>& deg )
		{
			radian -= Math::DegreesToRadian(deg);
			return *this;
		}

	}
}

#endif